home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
SCHEME
/
GNU
/
SCM4E1
/
!Scm
/
slib
/
yasos
< prev
Wrap
Text File
|
1993-05-18
|
7KB
|
298 lines
;; FILE "YASOS.scm"
;; IMPLEMENTS YASOS: Yet Another Scheme Object System
;; AUTHOR Kenneth Dickey
;; DATE 1992 March 1
;; LAST UPDATED 1992 September 1 -- misc optimizations
;; 1992 May 22 -- added SET and SETTER
;; REQUIRES R^4RS Syntax System
;; NOTES: A simple object system for Scheme based on the paper by
;; Norman Adams and Jonathan Rees: "Object Oriented Programming in
;; Scheme", Proceedings of the 1988 ACM Conference on LISP and Functional
;; Programming, July 1988 [ACM #552880].
;
;; Setters use space for speed {extra conses for O(1) lookup}.
;;
;; INTERFACE:
;;
;; (DEFINE-OPERATION (opname self arg ...) default-body)
;;
;; (DEFINE-PREDICATE opname)
;;
;; (OBJECT ((name self arg ...) body) ... )
;;
;; (OBJECT-WITH-ANCESTORS ( (ancestor1 init1) ...) operation ...)
;;
;; in an operation {a.k.a. send-to-super}
;; (OPERATE-AS component operation self arg ...)
;;
;; (SET var new-vale) or (SET (access-proc index ...) new-value)
;;
;; (SETTER access-proc) -> setter-proc
;; (DEFINE-ACCESS-OPERATION getter-name) -> operation
;; (ADD-SETTER getter setter) ;; setter is a Scheme proc
;; (REMOVE-SETTER-FOR getter)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; IMPLEMENTATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INSTANCES
; (define-predicate instance?)
; (define (make-instance dispatcher)
; (object
; ((instance? self) #t)
; ((instance-dispatcher self) dispatcher)
; ) )
(define yasos:make-instance 'bogus) ;; defined below
(define yasos:instance? 'bogus)
(define-syntax YASOS:INSTANCE-DISPATCHER ;; alias so compiler can inline for speed
(syntax-rules () ((yasos:instance-dispatcher inst) (cdr inst)))
)
(let ( (instance-tag "instance") ) ;; Make a unique tag within a local scope.
;; No other data object is EQ? to this tag.
(set! YASOS:MAKE-INSTANCE
(lambda (dispatcher) (cons instance-tag dispatcher)))
(set! YASOS:INSTANCE?
(lambda (obj) (and (pair? obj) (eq? (car obj) instance-tag))))
)
;; DEFINE-OPERATION
(define-syntax DEFINE-OPERATION
(syntax-rules ()
((define-operation (<name> <inst> <arg> ...) <exp1> <exp2> ...)
;;=>
(define <name>
(letrec ( (former-inst #f) ;; simple caching -- for loops
(former-method #f)
(self
(lambda (<inst> <arg> ...)
(cond
((eq? <inst> former-inst) ; check cache
(former-method <inst> <arg> ...)
)
((and (yasos:instance? <inst>)
((yasos:instance-dispatcher <inst>) self))
=> (lambda (method)
(set! former-inst <inst>)
(set! former-method method)
(method <inst> <arg> ...))
)
(else <exp1> <exp2> ...)
) ) ) )
self)
))
((define-operation (<name> <inst> <arg> ...) ) ;; no body
;;=>
(define-operation (<name> <inst> <arg> ...)
(slib:error "Operation not handled"
'<name>
(format #f (if (yasos:instance? <inst>) "#<INSTANCE>" "~s")
<inst>)))
))
)
;; DEFINE-PREDICATE
(define-syntax DEFINE-PREDICATE
(syntax-rules ()
((define-predicate <name>)
;;=>
(define-operation (<name> obj) #f)
)
) )
;; OBJECT
(define-syntax OBJECT
(syntax-rules ()
((object ((<name> <self> <arg> ...) <exp1> <exp2> ...) ...)
;;=>
(let ( (table
(list (cons <name>
(lambda (<self> <arg> ...) <exp1> <exp2> ...))
...
) )
)
(yasos:make-instance
(lambda (op)
(cond
((assq op table) => cdr)
(else #f)
) ) )))) )
;; OBJECT with MULTIPLE INHERITANCE {First Found Rule}
(define-syntax OBJECT-WITH-ANCESTORS
(syntax-rules ()
((object-with-ancestors ( (<ancestor1> <init1>) ... ) <operation> ...)
;;=>
(let ( (<ancestor1> <init1>) ... )
(let ( (child (object <operation> ...)) )
(yasos:make-instance
(lambda (op)
(or ((yasos:instance-dispatcher child) op)
((yasos:instance-dispatcher <ancestor1>) op) ...
) ) )
)))
) )
;; OPERATE-AS {a.k.a. send-to-super}
; used in operations/methods
(define-syntax OPERATE-AS
(syntax-rules ()
((operate-as <component> <op> <composit> <arg> ...)
;;=>
(((yasos:instance-dispatcher <component>) <op>) <composit> <arg> ...)
))
)
;; SET & SETTER
(define-syntax SET
(syntax-rules ()
((set (<access> <index> ...) <newval>)
((yasos:setter <access>) <index> ... <newval>)
)
((set <var> <newval>)
(set! <var> <newval>)
)
) )
(define yasos:add-setter 'bogus)
(define yasos:remove-setter-for 'bogus)
(define YASOS:SETTER
(let ( (known-setters (list (cons car set-car!)
(cons cdr set-cdr!)
(cons vector-ref vector-set!)
(cons string-ref string-set!))
)
(added-setters '())
)
(set! YASOS:ADD-SETTER
(lambda (getter setter)
(set! added-setters (cons (cons getter setter) added-setters)))
)
(set! YASOS:REMOVE-SETTER-FOR
(lambda (getter)
(cond
((null? added-setters)
(slib:error "REMOVE-SETTER-FOR: Unknown getter" getter)
)
((eq? getter (caar added-setters))
(set! added-setters (cdr added-setters))
)
(else
(let loop ((x added-setters) (y (cdr added-setters)))
(cond
((null? y) (slib:error "REMOVE-SETTER-FOR: Unknown getter"
getter))
((eq? getter (caar y)) (set-cdr! x (cdr y)))
(else (loop (cdr x) (cdr y)))
) ) )
) ) )
(letrec ( (self
(lambda (proc-or-operation)
(cond ((assq proc-or-operation known-setters) => cdr)
((assq proc-or-operation added-setters) => cdr)
(else (proc-or-operation self))) )
) )
self)
) )
(define (YASOS:MAKE-ACCESS-OPERATION <name>)
(letrec ( (setter-dispatch
(lambda (inst . args)
(cond
((and (yasos:instance? inst)
((yasos:instance-dispatcher inst) setter-dispatch))
=> (lambda (method) (apply method inst args))
)
(else #f)))
)
(self
(lambda (inst . args)
(cond
((eq? inst yasos:setter) setter-dispatch) ; for (setter self)
((and (yasos:instance? inst)
((yasos:instance-dispatcher inst) self))
=> (lambda (method) (apply method inst args))
)
(else (slib:error "Operation not handled" <name> inst))
) )
)
)
self
) )
(define-syntax DEFINE-ACCESS-OPERATION
(syntax-rules ()
((define-access-operation <name>)
;=>
(define <name> (yasos:make-access-operation '<name>))
) ) )
;;---------------------
;; general operations
;;---------------------
(define-operation (YASOS:PRINT obj port)
(format port
;; if an instance does not have a PRINT operation..
(if (yasos:instance? obj) "#<INSTANCE>" "~s")
obj
) )
(define-operation (YASOS:SIZE obj)
;; default behavior
(cond
((vector? obj) (vector-length obj))
((list? obj) (length obj))
((pair? obj) 2)
((string? obj) (string-length obj))
((char? obj) 1)
(else
(slib:error "Operation not supported: size" obj))
) )
(require 'format)
;;; exports:
(define print yasos:print) ; print also in debug.scm
(define size yasos:size)
(define add-setter yasos:add-setter)
(define remove-setter-for yasos:remove-setter-for)
(define setter yasos:setter)
(provide 'oop) ;in case we were loaded this way.
;; --- E O F "yasos.scm" --- ;;